package cn.jofei.common.netty.protocol;

import cn.jofei.common.config.AppProperties;
import cn.jofei.common.netty.message.Message;
import com.alibaba.fastjson2.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 编码解码器
 *
 * @author Jofei Bao
 * @version learn-demo v2.0
 * @date 2022年10月21日 15:34
 */
@ChannelHandler.Sharable
public class MessageCodec extends MessageToMessageCodec<ByteBuf, Message> {

    /**
     * 序列化方式 0：jdk ；1：json
     */
    private final int type = AppProperties.get("serialize.type", Integer.class).orElse(1);

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Message message, List<Object> list) throws Exception {
        ByteBuf byteBuf = channelHandlerContext.alloc().buffer();
        //魔数 用来第一时间判断是否为有效的数据包
        byteBuf.writeBytes(new byte[]{'a', 'b', 'a', 'o'});
        //版本
        byteBuf.writeByte(1);
        //序列化方式
        byteBuf.writeByte(type);
        //指令类型，可找对应的类
        byteBuf.writeByte(message.getMsgType());
        //序列号 int 4 字节
        byteBuf.writeInt(message.getSequenceId());
        //对齐 无效byte
        byteBuf.writeByte(0xff);
        //获取序列化后的数组
        if (type == 0) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(out);
            oos.writeObject(message);
            //内容长度
            byteBuf.writeInt(out.size());
            //内容
            byteBuf.writeBytes(out.toByteArray());
            out.close();
        } else if (type == 1) {
            byte[] bytes = JSON.toJSONString(message).getBytes(StandardCharsets.UTF_8);
            //内容长度
            byteBuf.writeInt(bytes.length);
            //内容
            byteBuf.writeBytes(bytes);
        }
        list.add(byteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        //魔数
        int magicNum = byteBuf.readInt();
        //版本
        int version = byteBuf.readByte();
        //序列化方式
        int serializerType = byteBuf.readByte();
        //指令类型，可找对应的类
        int msgType = byteBuf.readByte();
        //序列号
        int sequenceId = byteBuf.readInt();
        byteBuf.readByte();
        //内容长度
        int len = byteBuf.readInt();
        byte[] bytes = new byte[len];
        byteBuf.readBytes(bytes, 0, len);
        Object o = null;
        if (serializerType == 0) {
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
            o = ois.readObject();
        } else if (serializerType == 1) {
            o = JSON.parseObject(new String(bytes, StandardCharsets.UTF_8), Message.class);
        }
        list.add(o);
    }
}
